<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<script src="./node_modules/vue/dist/vue.js"></script>
<body>
<!--
1、app.message修改数据，Vue内部是如何监听数据的改变
- Object.defineProperty -> 监听对象属性的改变

2、当数据发上改变时，Vue是如何知道要通知那些人？
- 发布订阅者模式
-->


  <div id="app">
    {{message}}
    {{message}}
    {{message}}
  </div>

  <script>
    const obj = {
      message: '哈哈哈',
      name: '云澈'
    }
    //通过下面的遍历拿到对象的数据
    Object.keys(obj).forEach(key => {
      let value = obj[key];
      //通过下面的方法监听数据改变
      Object.defineProperty(obj, key, {
        //监听key的改变set设置，get返回
        //告诉谁了？谁用就告诉谁
        //根据解析HTML代码，获取到那些人有用属性
        //message1、message2、message3 各自调用get
        set(newValue) {
          console.log('监听' + key + '改变');
          value = newValue;

          //当监听到对象呗调用，则发出notify
          dep.notify()
        },
        get() {
          console.log('获取' + key + '对应的值');
          return value;
        }
      })
    })

    //发布者订阅者（类似于观察者模式）
    class Dep {
      constructor() {
        //次数组用于记录谁 使用 属性了
        this.subscribes = []
      }
      //添加订阅者
      addSub(watch) {
        this.subscribes.push(watch);
      }

      //通知方法
      notify() {
        this.subscribes.forEach(item => {
          item.update();
        })
      }
    }
    //订阅者对象
    class Watch {
      constructor(name) {
        this.name = name;
      }
      update() {
        console.log(this.name + '发生了update');
      }
    }

    const dep = new Dep();

    const w1 = new Watch('张三');
    dep.addSub(w1);
    const w2 = new Watch('李四');
    dep.addSub(w2);
    const w3 = new Watch('王五');
    dep.addSub(w3);

    dep.notify()
  </script>

  <script>
    const app = new Vue({
      el: '#app',
      data: {
        message: '哈哈哈',
        name: '云澈'
      }

    })
  </script>
</body>


</html>